home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 6
/
QRZ Ham Radio Callsign Database - Volume 6.iso
/
pc
/
files
/
t_jnos
/
jnos_qrz.c
< prev
next >
Wrap
Text File
|
1994-07-11
|
15KB
|
542 lines
// June 15, 1994 - KF5MG - Jack Snodgrass
//
// This code was adapted/copied from the SAM.C code. The code to process
// the QRZ disk was taken from the QRZ CD-ROM. This code could work
// with the name and zipcode versions of the Callbook data, but as-is, it
// only processes callsigns.
//
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#define reclen 160
#include "global.h"
#ifdef QRZCALLB
#include "mbuf.h"
#include "socket.h"
#include "session.h"
#include "proc.h"
#include "netuser.h"
#include "commands.h"
#include "tty.h"
#include "config.h"
extern char *Callserver; /* buckbook.c */
int cb_lookup __ARGS((int s,char *,FILE *));
/* does the actual lookup. */
int qrzfind(char *,int s, FILE *);
/* Parse QRZ data record. */
void parse_record(char *, int s);
/* Format QRZ Database Date. */
void formatdate(char *);
/* Gobal variables. */
char pretty_date[12];
char prettycall[7];
char *qrzdir;
char *qrzdrv;
/* Taken from the QRZ CD-ROM disk.
* This block is located at the start of each index
*/
/*
* New Index Header Block Definition
*/
typedef struct {
char dataname[16]; /* Name of the data file */
char bytesperkey[8]; /* Data Bytes per Index Item */
char numkeys[8]; /* Number of items in this index */
char keylen[8]; /* Length of each key item in bytes */
char version[8]; /* Database Version ID */
} index_header;
/*
* Old Index Header Block Definition
*/
typedef struct {
char dataname[13]; /* Name of the data file */
long bytesperkey; /* Data Bytes per Index Item */
int numkeys; /* Number of items in this index */
int keylen; /* Length of each key item in bytes */
} old_index_header ;
/* return values - 2= Callbook Error 1= not found, 0= okay */
int cb_lookup(s, str, fp)
int s;
char *str;
FILE *fp;
{
if(qrzfind(str,s,fp))
return 0;
else
return 1;
}
int qrzfind(char *call_in, int s, FILE *fpout)
{
index_header idxhdr;
old_index_header oldidxhdr;
FILE *fp;
char *buf;
char *bufptr;
char IndexFile[] = "callbkc.idx";
int size;
int bytesperkey; /* Data Bytes per Index Item */
int numkeys; /* Number of items in this index */
int keylen; /* Length of each key item in bytes */
int slots;
int i,j,k,found,slotcnt;
long fpos;
long frc;
char temp[255];
char *cp;
char *cp2;
char call[8];
/* call needs to be blank filled. */
strcpy(call," ");
/* Pretty call holds the original, un-qrz-formatted callsign. */
strcpy(prettycall, call_in);
strupr(prettycall);
k = strlen(call_in);
if (k>6) {
usprintf(s,"Callsign too long.\n");
return 0;
}
/* Callsigns in the QRZ Index are stored in a weird format. They are */
/* 6 characters in length ( padded with spaces ), in the format of */
/* ccdccc where the digit is always in the 3rd posistion. If the */
/* callsign is a 1-by-something callsign, the 2nd posistion will be */
/* blank. KF5MG will be stored as KF5MGb. N5VGC will be stored as */
/* Nb5VGC. ( the b are spaces ) */
/* */
i = 1;
j = 1;
call[0] = call_in[0];
if(!isdigit(call_in[j]))
call[i++] = call_in[j++];
else
call[i++] = ' ';
if(isdigit(call_in[j])) {
call[i++] = call_in[j++];
} else {
/* No digit found in posistion 2 or 3. */
usprintf(s,"Error parsing callsign... %s\n", call_in);
return 0;
}
if(isalpha(call_in[j]))
call[i++] = call_in[j];
else
call[i++] = ' ';
j++;
if(isalpha(call_in[j]))
call[i++] = call_in[j];
else
call[i++] = ' ';
j++;
if(isalpha(call_in[j]))
call[i++] = call_in[j];
else
call[i++] = ' ';
call[6] = 0;
strupr(call);
qrzdir = strdup(getenv("QRZPATH"));
qrzdrv = strdup(getenv("QRZDRV"));
if(qrzdir == NULLCHAR)
qrzdir = strdup("\\callbk");
if(qrzdrv == NULLCHAR)
qrzdrv = strdup("C:");
/* Open the index file. We'll use it to tell us the name of the */
/* database file. We'll also find the database version and some */
/* other useful info. */
/* */
sprintf(temp,"%s%s\\%s",qrzdrv,qrzdir,IndexFile);
if((fp = fopen(temp,"rt"))==NULL) {
usprintf(s,"Error opening Index: %s\n",temp);
free(qrzdir);
free(qrzdrv);
return 0;
}
size = fread(&idxhdr,sizeof(idxhdr),1,fp);
if(size != 1) {
usprintf(s,"Error reading Index Header.\n");
free(qrzdir);
free(qrzdrv);
return 0;
}
// Old Style Index has a '0' at pos 16 and 17.
if((int)idxhdr.dataname[16] != 0) {
// This is a 'new' style index
bytesperkey = atoi(idxhdr.bytesperkey); /* size of data area. */
numkeys = atoi(idxhdr.numkeys); /* # of keys in file. */
keylen = atoi(idxhdr.keylen); /* length of each key. */
} else {
// This is an 'old' style index.
// rewind the file and read the header using the old_index_header struct.
rewind(fp);
size = fread(&oldidxhdr,sizeof(oldidxhdr),1,fp);
if(size != 1) {
usprintf(s,"Error reading Index Header.\n");
free(qrzdir);
free(qrzdrv);
return 0;
}
bytesperkey = oldidxhdr.bytesperkey; /* size of data area. */
numkeys = oldidxhdr.numkeys; /* # of keys in file. */
keylen = oldidxhdr.keylen; /* length of each key. */
}
/* This is a 10K ish buffer. Each 'key' in the index covers almost */
/* 10K of data. Once you find the correct key, you have to read the */
/* 10K chunk of data from the data file. You then start searching */
/* for the correct callsign. This code uses the same 10k buffer to */
/* scan the index file ( typically 40K so you might do 4 reads ) to */
/* save memory. Once you've found the correct key, you calculate the */
/* offset into the database. You then read the data base into your */
/* 10K buffer.
/* */
bufptr = malloc(bytesperkey+400); /* Get space for buffer */
slots = bytesperkey / keylen; /* Calculate # of slots */
found = 0;
slotcnt = 0;
do {
/* Point floating buf pointer to start of big buffer. */
buf = bufptr;
/* Read slots number of entries that are keylen in size */
size = fread(buf,keylen,slots,fp);
if(size == 0) {
usprintf(s,"Error reading Index file.\n");
found = 2;
}
/* Start scanning Index buffer. If the data is less than your search */
/* Value... keep going. If the Data is greater, then your done. You */
/* then subtract one from your slotcnt (unless it's an exact match) */
/* and that's the closet record to your data. */
/* */
for(i=0;i<size;i++) {
slotcnt++;
strncpy(temp,(char *)buf,keylen);
temp[keylen] = 0;
if(strncmp(&temp[3],&call[3],3) >= 0) {
if(strncmp(&temp[3],&call[3],3) > 0) {
found = 1;
slotcnt--;
}
else
if(strncmp(&temp[2],&call[2],4) > 0) {
slotcnt--;
found = 1;
}
}
if(found)
break;
/*
*buf++;
*buf++;
*buf++;
*buf++;
*buf++;
*buf++;
*/
buf += 6;
}
} while(!found); /* enddo */
slotcnt--;
/* We're done with the Index so we can close it. */
fclose(fp);
/* If we found a match, the calculate the offset and read the data. */
if(found == 1) {
buf = bufptr;
sprintf(temp,"%s%s\\%s",qrzdrv,qrzdir,idxhdr.dataname);
if((fp = fopen(temp,"rt"))==NULL) {
usprintf(s,"Error opening Database: %s\n",temp);
free(bufptr);
free(qrzdir);
free(qrzdrv);
return 0;
}
/* Just to to be save, we read 200 bytes before and after so we */
/* don't miss anything. */
/* seek to correct posistion in file . */
fpos = (long) bytesperkey*slotcnt;
fpos -= 200;
frc = lseek(fileno(fp),(long) fpos,SEEK_SET);
if(frc < 1) {
usprintf(s,"Error seeking Database file.\n");
free(bufptr);
free(qrzdir);
free(qrzdrv);
return 0;
}
/* Read slot from callbk file. */
size = fread(buf,bytesperkey+400,1,fp);
if(size < 1) {
usprintf(s,"Error reading Database file.\n");
free(bufptr);
free(qrzdir);
free(qrzdrv);
return 0;
}
/* Done with data file. Now we can close it too. Our users is either */
/* in our buffer or doesn't exist. */
fclose(fp);
i = 0;
for(;;) {
if(i>bytesperkey+400)
break;
k = strcspn(buf,"\n");
strncpy(temp,buf,k);
temp[k] = 0;
for(j=0;j<=k;j++)
/*
*buf++;
*/
buf += 1;
/* Find our user. */
if(strncmp(temp,call,6) == 0) {
/* Found it. Now read and format the data. */
parse_record(temp,s);
break;
}
i+=k;
}
}
/* Done with the buffer. */
free(bufptr);
free(qrzdir);
free(qrzdrv);
return found;
}
void parse_record(char *record, int s) {
/*
* Standard Record Format
*/
char callsign[7]; /* Call Sign Decoded */
char lastname[33]; /* Last Name */
char namesuffix[3]; /* Name Suffix */
char frstname[33]; /* First Name */
char middleinit[3]; /* Middle Initial */
char datelicensed[6]; /* Date Licensed mm/dd/yy */
char dateborn[6]; /* Date Born */
char dateexpires[6]; /* Date Born */
char streetaddr[33]; /* Street Address */
char city[33]; /* City */
char state[3]; /* State Code */
char zipcode[6]; /* Zip Code */
char license_class[3]; /* License Class */
char prevcall[7]; /* Previous Call */
char prevclass[3]; /* Previous Class */
char *cp;
char fullname[80];
char address[80];
char temp[255];
char temp2[255];
int i,j,k;
strcpy(temp2,record);
cp = temp2;
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(callsign,temp);
if(strlen(record) < 16) {
usprintf(s,"%s is an old call for %s\n", prettycall, cp);
return;
}
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(lastname,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(namesuffix,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(frstname,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(middleinit,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(dateborn,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(datelicensed, temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(dateexpires,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(streetaddr,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(city,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(state,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(zipcode,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(license_class,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(prevcall,temp);
k = strcspn(cp,",");
strncpy(temp,cp,k);
temp[k] = 0;
for(j=0;j<=k;j++)
cp += 1;
strcpy(prevclass,temp);
sprintf(fullname,"%s %s. %s, %s",frstname, middleinit, lastname, namesuffix);
sprintf(address, "%s, %s, %s", city, state, zipcode);
usprintf(s,"\n%-8s", prettycall);
usprintf(s,"%-45s", fullname);
formatdate(dateborn);
usprintf(s,"Born: %s\n", pretty_date);
usprintf(s,"%-8s%-45s","", streetaddr);
formatdate(datelicensed);
usprintf(s,"Class: %s %s\n", license_class, pretty_date);
usprintf(s,"%-8s%-45s", "", address);
usprintf(s,"Prev: %s %s\n", prevclass, prevcall);
formatdate(dateexpires);
usprintf(s,"%52s Expir: %s\n", "", pretty_date);
return;
}
void formatdate(char *date){
char year[5];
char rest[4];
int mon;
int day;
int days;
int years;
int i;
int dayarray[12] = { 31, 60, 91, 121, 152, 182,
213, 244, 274, 305, 335, 366 };
strncpy(year,date,2);
year[2] = 0;
years = atoi(year);
if(years < 20)
years += 2000;
else
years += 1900;
strncpy(rest,&date[2],3);
rest[3] = 0;
days = atoi(rest);
if((years % 4) != 0)
if(days > 59)
days++;
for(i=0;i<12;i++){
if(days <= dayarray[i]) {
mon = i;
day = days - dayarray[i-1];
break;
}
}
sprintf(pretty_date, "%02d/%02d/%04d", mon+1,day,years);
}
#endif